#include "QtWidgetsApplication1.h"
int biBitCount = 24;
void QtWidgetsApplication1::qhui()
{
    c->hui();
    QImage* img = new QImage();
    img->load(file);
    QImage* newImage = new QImage(*img);
    newImage->save("end.bmp");
    c->WriteBMP("end.bmp");
    p->load("end.bmp");
    ui.able->setPixmap(QPixmap::fromImage(*p));
    ui.able->show();
}
void QtWidgetsApplication1::qflip1()
{
    c->Flip(1);
    QImage* img = new QImage();
    img->load(file);
    QImage* newImage = new QImage(*img);
    newImage->save("end.bmp");
    c->WriteBMP("end.bmp");
    p->load("end.bmp");
    ui.able->setPixmap(QPixmap::fromImage(*p));
    ui.able->show();
}
void QtWidgetsApplication1::qflip2()
{
    c->Flip(0);
    QImage* img = new QImage();
    img->load(file);
    QImage* newImage = new QImage(*img);
    newImage->save("end.bmp");
    c->WriteBMP("end.bmp");
    p->load("end.bmp");
    ui.able->setPixmap(QPixmap::fromImage(*p));
    ui.able->show();
}
void QtWidgetsApplication1::qread()
{
    file = QFileDialog::getOpenFileName(this, "choose picture",
        "", "*bmp");
    //未选择，提示并退出
    if (file == "") {
        QMessageBox::information(this, tr("System message"), tr("Don't choose picture"), QMessageBox::Ok);
        return;
    }
    ui.lineEdit_test->setText(file);
    QByteArray ba;
    char* temp;
    char a[100];
    ba = file.toLatin1();
    temp = ba.data();
    strncpy(a, temp, 100);
    c->ReadBMP(a);
    QImage* img = new QImage();
    img->load(file);
    QImage* newImage = new QImage(*img);
    newImage->save("end.bmp");
    c->WriteBMP("end.bmp");
    p->load("end.bmp");
    ui.able->setPixmap(QPixmap::fromImage(*p));
    //ui.able->show();
}
void QtWidgetsApplication1::qresize1()
{
    c->Resize(1);
    QImage* img = new QImage();
    img->load(file);
    QImage* newImage = new QImage(*img);
    newImage->save("end.bmp");
    c->WriteBMP("end.bmp");
    p->load("end.bmp");
    ui.able->setPixmap(QPixmap::fromImage(*p));
    ui.able->show();
}
void QtWidgetsApplication1::qresize2()
{
    c->Resize(0);
    QImage* img = new QImage();
    img->load(file);
    QImage* newImage = new QImage(*img);
    newImage->save("end.bmp");
    c->WriteBMP("end.bmp");
    p->load("end.bmp");
    ui.able->setPixmap(QPixmap::fromImage(*p));
    ui.able->show();
}
void QtWidgetsApplication1::qrotate()
{
    c->Rotate(90);
    QImage* img = new QImage();
    img->load(file);
    QImage* newImage = new QImage(*img);
    newImage->save("end.bmp");
    c->WriteBMP("end.bmp");
    p->load("end.bmp");
    ui.able->setPixmap(QPixmap::fromImage(*p));
    ui.able->show();
}
void QtWidgetsApplication1::qCrop()
{
    QString str = ui.lineEdit->text();
    QString str2 = ui.lineEdit_2->text();
    QString str3 = ui.lineEdit_3->text();
    QString str4 = ui.lineEdit_4->text();
    int a[4];
    a[0] = str.toInt();
    a[1] = str2.toInt();
    a[2] = str3.toInt();
    a[3] = str4.toInt();
    c->Crop(a[0], a[1], a[2], a[3]);
    QImage* img = new QImage();
    img->load(file);
    QImage* newImage = new QImage(*img);
    newImage->save("end.bmp");
    c->WriteBMP("end.bmp");
    p->load("end.bmp");
    ui.able->setPixmap(QPixmap::fromImage(*p));
    ui.able->show();
}
QtWidgetsApplication1::QtWidgetsApplication1(QWidget* parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    this->setWindowTitle("choose function");
    b = new QPushButton("udflip", this);
    b->show();
    b->move(100, 330);
    b1 = new QPushButton("read", this);
    b1->show();
    b1->move(100, 30);
    b2 = new QPushButton("lrflip", this);
    b2->show();
    b2->move(300, 330);
    b3 = new QPushButton("enlargement", this);
    b3->show();
    b3->move(100, 430);
    b4 = new QPushButton("shrink", this);
    b4->show();
    b4->move(300, 430);
    b5 = new QPushButton("rotate", this);
    b5->show();
    b5->move(100, 230);
    p = new QImage();
    connect(b, &QPushButton::clicked, this, &QtWidgetsApplication1::qflip1);
    connect(b1, &QPushButton::clicked, this, &QtWidgetsApplication1::qread);
    connect(b2, &QPushButton::clicked, this, &QtWidgetsApplication1::qflip2);
    connect(b3, &QPushButton::clicked, this, &QtWidgetsApplication1::qresize1);
    connect(b4, &QPushButton::clicked, this, &QtWidgetsApplication1::qresize2);
    connect(b5, &QPushButton::clicked, this, &QtWidgetsApplication1::qrotate);
    connect(ui.pushButton, &QPushButton::clicked, this, &QtWidgetsApplication1::qCrop);
    connect(ui.pushButton_2, &QPushButton::clicked, this, &QtWidgetsApplication1::qhui);
    connect(ui.pushButton_5, &QPushButton::clicked, this, &QtWidgetsApplication1::on_pushButton_5_clicked);
    connect(ui.pushButton_4, &QPushButton::clicked, this, &QtWidgetsApplication1::on_pushButton_4_clicked);
    connect(ui.pushButton_3, &QPushButton::clicked, this, &QtWidgetsApplication1::on_pushButton_3_clicked);
}
//构造函数
bImage::bImage()
{
    height = 0;
    width = 0;
    data = NULL;
}
//构造函数重载
bImage::bImage(int h, int w)
{
    height = h;
    width = w;
    data = new unsigned char* [h];
    int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
    for (int i = 0;i < h;i++)
    {
        for (int j = 0;j < lineByte;j++)
        {
            data[i] = new unsigned char[lineByte];
        }
    }
}
//构造函数重载，创建的图像像素值都为val;
bImage::bImage(int h, int w, unsigned char val)
{
    height = h;
    width = w;
    data = new unsigned char* [h];
    int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
    for (int i = 0;i < h;i++)
    {
        data[i] = new unsigned char[lineByte];
    }
    for (int i = 0;i < h;i++)
    {
        for (int j = 0;j < lineByte;j++)
        {
            data[i][j] = val;
        }
    }
}
//构造函数重载，利用文件名从硬盘加载图像文件成为Image对象;
bImage::bImage(char* ImageName)
{
    FILE* fp;
    fopen_s(&fp, ImageName, "rb");//二进制读方式打开指定的图像文件
    fseek(fp, sizeof(BITMAPFILEHEADER), 0);
    BITMAPINFOHEADER head;
    fread(&head, sizeof(BITMAPINFOHEADER), 1, fp); //获取图像宽、高、每像素所占位数等信息
    height = head.biHeight;
    width = head.biWidth;
    biBitCount = head.biBitCount;//定义变量，计算图像每行像素所占的字节数（必须是4的倍数）
    int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
    //申请位图数据所需要的空间，读位图数据进内存        
    data = new unsigned char* [height];
    for (int i = 0;i < height;i++)
    {
        data[i] = new unsigned char[lineByte];
    }
    for (int i = 0;i < height; i++)
    {
        for (int j = 0;j < lineByte;j++)
            fread(&data[i][j], 1, sizeof(unsigned char), fp);
    }
    fclose(fp);//关闭文件 
}

//拷贝构造函数
bImage::bImage(const bImage& im)
{
    height = im.height;
    width = im.width;
    data = new unsigned char* [im.height];
    int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
    for (int i = 0;i < im.height;i++)
    {
        data[i] = new unsigned char[lineByte];
    }
    for (int i = 0;i < height; i++)
    {
        for (int j = 0; j < lineByte; j++)
        {
            data[i][j] = im.data[i][j];
        }
    }
}


//析构函数

bImage::~bImage()
{
    if (data != NULL)
    {
        for (int i = 0;i < height;i++)
        {
            delete data[i];
        }
        delete data;
    }
}

//从硬盘读入图像文件; 
void bImage::ReadBMP(char* filename)
{
    FILE* fp;
    fopen_s(&fp, filename, "rb");//二进制读方式打开指定的图像文件
    fseek(fp, sizeof(BITMAPFILEHEADER), 0);
    BITMAPINFOHEADER head;
    fread(&head, sizeof(BITMAPINFOHEADER), 1, fp); //获取图像宽、高、每像素所占位数等信息
    height = head.biHeight;
    width = head.biWidth;
    biBitCount = head.biBitCount;//定义变量，计算图像每行像素所占的字节数（必须是4的倍数）
    int lineByte = (head.biWidth * biBitCount / 8 + 3) / 4 * 4;//灰度图像有颜色表，且颜色表表项为256
    //申请位图数据所需要的空间，读位图数据进内存        
    data = new unsigned char* [height];
    for (int i = 0;i < height;i++)
    {
        data[i] = new unsigned char[lineByte];
    }
    for (int i = 0;i < height;i++)
    {
        for (int j = 0;j < lineByte;j++)
        {
            fread(&data[i][j], 1, 1, fp);
        }
    }
    fclose(fp);//关闭文件 
}


//保存图像; 
void bImage::WriteBMP(char* filename)
{
    FILE* fp;
    fopen_s(&fp, filename, "wb");//二进制读方式打开指定的图像文件
    //申请位图文件头结构变量，填写文件头信息
    BITMAPFILEHEADER fileHead;
    fileHead.bfType = 0x4D42;//bmp类型   
    int colorTablesize = 0;
    //bfSize是图像文件4个组成部分之和   
    int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
    fileHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + colorTablesize + lineByte * height;
    fileHead.bfReserved1 = 0;
    fileHead.bfReserved2 = 0;
    //bfOffBits是图像文件前3个部分所需空间之和     
    fileHead.bfOffBits = 54 + colorTablesize;
    //写文件头进文件     
    fwrite(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp);
    BITMAPINFOHEADER head;
    head.biBitCount = biBitCount;
    head.biClrImportant = 0;
    head.biClrUsed = 0;
    head.biCompression = 0;
    head.biHeight = height;
    head.biPlanes = 1;
    head.biSize = 40;
    head.biSizeImage = lineByte * height;
    head.biWidth = width;
    head.biXPelsPerMeter = 0;
    head.biYPelsPerMeter = 0;
    //写位图信息头进内存
    //写位图信息头进内存
    fwrite(&head, sizeof(BITMAPINFOHEADER), 1, fp);
    //写位图数据进文件
    for (int i = 0;i < height;i++)
    {
        for (int j = 0;j < lineByte;j++)
        {
            fwrite(&data[i][j], 1, 1, fp);
        }
    }
    //关闭文件
    fclose(fp);
}
void bImage::Flip(int code)
{
    if (code == 0)
    {
        unsigned char** a;
        a = new unsigned char* [height];
        int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
        for (int i = 0;i < height;i++)
        {
            a[i] = new unsigned char[lineByte];
        }
        for (int i = 0;i < height;i++)
        {
            for (int j = 0;j < lineByte;j++)
            {
                a[i][j] = data[i][j];
            }
        }
        for (int i = 0;i < height;i++)
        {
            for (int j = 0;j < lineByte;j = j + 3)
            {
                data[i][j] = a[i][lineByte - j - 3];
                data[i][j + 1] = a[i][lineByte - j - 2];
                data[i][j + 2] = a[i][lineByte - j - 1];
            }
        }
        for (int i = 0;i < height;i++)
        {
            delete[lineByte]a[i];
        }
        delete[height]a;
    }
    else
    {
        unsigned char** a;
        a = new unsigned char* [height];
        int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
        for (int i = 0;i < height;i++)
        {
            a[i] = new unsigned char[lineByte];
        }
        for (int i = 0;i < height;i++)
        {
            for (int j = 0;j < lineByte;j++)
            {
                a[i][j] = data[i][j];
            }
        }
        for (int i = 0;i < height;i++)
        {
            for (int j = 0;j < lineByte;j++)
            {
                data[i][j] = a[height - 1 - i][j];
            }
        }
        for (int i = 0;i < height;i++)
        {
            delete[lineByte]a[i];
        }
        delete[height]a;
    }
}

//图像缩小，放大
void bImage::Resize(int code)
{
    if (code == 0)
    {
        unsigned char** a;
        a = new unsigned char* [height];
        int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
        for (int i = 0;i < height;i++)
        {
            a[i] = new unsigned char[lineByte];
        }
        for (int i = 0;i < height;i++)
        {
            for (int j = 0;j < lineByte;j++)
            {
                a[i][j] = data[i][j];
            }
        }
        //for (int i = 0;i < height;i++)
        //{
            //delete [lineByte]data[i];
        //}
        //delete [height]data;
        height = height / 2;
        width = width / 2;
        data = new unsigned char* [height];
        lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
        for (int i = 0;i < height;i++)
        {
            data[i] = new unsigned char[lineByte];
        }
        for (int i = 0;i < height;i++)
        {
            for (int j = 0;j < lineByte;j = j + 3)
            {
                data[i][j] = a[2 * i][2 * j];
                data[i][j + 1] = a[2 * i][2 * j + 1];
                data[i][j + 2] = a[2 * i][2 * j + 2];
            }
        }
        for (int i = 0;i < 2 * height;i++)
        {
            delete[lineByte]a[i];
        }
        delete[height]a;
    }
    else
    {
        unsigned char** a;
        a = new unsigned char* [height];
        int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
        for (int i = 0;i < height;i++)
        {
            a[i] = new unsigned char[lineByte];
        }
        for (int i = 0;i < height;i++)
        {
            for (int j = 0;j < lineByte;j++)
            {
                a[i][j] = data[i][j];
            }
        }
        //for (int i = 0;i < height;i++)
        //{
           //delete [lineByte]data[i];
        //}
        //delete [height]data;
        height = 2 * height;
        width = 2 * width;
        data = new unsigned char* [height];
        lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
        for (int i = 0;i < height;i++)
        {
            data[i] = new unsigned char[lineByte];
        }
        for (int i = 0;i < height;i = i + 2)
        {
            for (int j = 0;j < lineByte;j = j + 6)
            {
                data[i][j] = a[i / 2][j / 2];
                data[i][j + 1] = a[i / 2][j / 2 + 1];
                data[i][j + 2] = a[i / 2][j / 2 + 2];
                data[i][j + 3] = a[i / 2][j / 2];
                data[i][j + 4] = a[i / 2][j / 2 + 1];
                data[i][j + 5] = a[i / 2][j / 2 + 2];

            }
            for (int j = 0;j < lineByte;j = j + 6)
            {
                data[i + 1][j] = a[i / 2][j / 2];
                data[i + 1][j + 1] = a[i / 2][j / 2 + 1];
                data[i + 1][j + 2] = a[i / 2][j / 2 + 2];
                data[i + 1][j + 3] = a[i / 2][j / 2];
                data[i + 1][j + 4] = a[i / 2][j / 2 + 1];
                data[i + 1][j + 5] = a[i / 2][j / 2 + 2];

            }
        }
        for (int i = 0;i < height / 2;i++)
        {
            delete[lineByte]a[i];
        }
        delete[height]a;
    }
}

void bImage::Crop(int x1, int y1, int x2, int y2)//图像裁剪的函数
{
    unsigned char** a;
    a = new unsigned char* [height];
    int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
    for (int i = 0;i < height;i++)
    {
        a[i] = new unsigned char[lineByte];
    }
    for (int i = 0;i < height;i++)
    {
        for (int j = 0;j < lineByte;j++)
        {
            a[i][j] = data[i][j];
        }
    }
    //for (int i = 0;i < height;i++)
    //{
        //delete[lineByte]data[i];
    //}
    //delete [height]data;
    height = y2 - y1 + 1;
    width = x2 - x1 + 1;
    data = new unsigned char* [height];
    lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
    for (int i = 0;i < height;i++)
    {
        data[i] = new unsigned char[lineByte];
    }
    int temp = x1;
    for (int i = 0;i < height;i++)
    {
        for (int j = 0;j < lineByte;j = j + 3)
        {
            data[i][j] = a[y1][3 * x1 + j];
            data[i][j + 1] = a[y1][3 * x1 + j + 1];
            data[i][j + 2] = a[y1][3 * x1 + j + 2];
            //x1++;
        }
        //x1 = temp;
        y1++;
    }
    for (int i = 0;i < height;i++)
    {
        delete[lineByte]a[i];
    }
    delete[height]a;
}
void bImage::Rotate(int degree) //图像旋转的函数
{
    int n;
    n = degree / 90;
    while (n) {
        unsigned char** a;
        a = new unsigned char* [height];
        int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
        for (int i = 0;i < height;i++)
        {
            a[i] = new unsigned char[lineByte];
        }
        for (int i = 0;i < height;i++)
        {
            for (int j = 0;j < lineByte;j++)
            {
                a[i][j] = data[i][j];
            }
        }
        //for (int i = 0;i < height;i++)
        //{
            //delete [lineByte]data[i];
        //}
        //delete [height]data;
        int temp = height;
        height = width;
        width = temp;
        data = new unsigned char* [height];
        lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
        for (int i = 0;i < height;i++)
        {
            data[i] = new unsigned char[lineByte];
        }
        for (int i = 0;i < height;i++)
        {
            int flag = 0;
            for (int j = 0;j < width;j++)
            {
                data[i][flag] = a[width - j - 1][3 * i];
                data[i][flag + 1] = a[width - j - 1][3 * i + 1];
                data[i][flag + 2] = a[width - j - 1][3 * i + 2];
                flag += 3;
            }
        }
        lineByte = (height * biBitCount / 8 + 3) / 4 * 4;
        for (int i = 0;i < width;i++)
        {
            delete[lineByte]a[i];
        }
        delete[width]a;
        n--;
    }
}
void bImage::hui()
{
    unsigned char** a;
    a = new unsigned char* [height];
    int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
    for (int i = 0;i < height;i++)
    {
        a[i] = new unsigned char[lineByte];
    }
    for (int i = 0;i < height;i++)
    {
        for (int j = 0;j < lineByte;j++)
        {
            a[i][j] = data[i][j];
        }
    }
    for (int i = 0;i < height;i++)
    {
        for (int j = 0;j < width;j++)
        {
            data[i][3 * j] = (a[i][3 * j + 2] + a[i][3 * j + 1] + a[i][3 * j]) / 3;
            data[i][3 * j + 1] = (a[i][3 * j + 2] + a[i][3 * j + 1] + a[i][3 * j]) / 3;
            data[i][3 * j + 2] = (a[i][3 * j + 2] + a[i][3 * j + 1] + a[i][3 * j]) / 3;
        }
    }
}
void QtWidgetsApplication1::on_pushButton_5_clicked()
{
    img= new QImage;
    //读入失败，退出
    if (!(img->load("end.bmp"))) {
        QMessageBox::information(this, tr("System message"), tr("Operation failed"));
        delete img;
        return;
    }

    QImage* newImage = new QImage(img->width(), img->height(), QImage::Format_ARGB32);

    QColor oldColor;
    QColor newColor;
    int h, s, l;
    int delta = 30;

    for (int x = 0; x < newImage->width(); x++) {
        for (int y = 0; y < newImage->height(); y++) {
            oldColor = QColor(img->pixel(x, y));

            newColor = oldColor.toHsl();
            h = newColor.hue();
            s = newColor.saturation() + delta;
            l = newColor.lightness();

            //we check if the new value is between 0 and 255
            s = qBound(0, s, 255);

            newColor.setHsl(h, s, l);

            newImage->setPixel(x, y, qRgb(newColor.red(), newColor.green(), newColor.blue()));
        }
    }

    //存本地
    newImage->save("saturation.bmp");
    p->load("saturation.bmp");
    ui.label_2->setPixmap(QPixmap::fromImage(*p));
    ui.label_2->show();
    //显示
    //QImage转QPixmap
    //QPixmap p;
    //p = p.fromImage(*newImage);
    //重新设置图片的宽高
    //int pwidth = ui.label_2->width();
    //int pheight = ui.label_2->height();
    //QPixmap new_p = p.scaled(Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    //显示图片在第二个Label控件中
    //ui.label_2->setPixmap(new_p);
    //图片随label框等比例缩放
    //ui.label_2->setScaledContents(true);
}
void QtWidgetsApplication1::on_pushButton_4_clicked()
{
    img = new QImage;
    //读入失败，退出
    if (!(img->load("end.bmp"))) {
        QMessageBox::information(this, tr("System message"), tr("Operation failed"));
        delete img;
        return;
    }

    QImage* newImage = new QImage(img->width(), img->height(), QImage::Format_ARGB32);

    QColor oldColor;
    int r, g, b;
    int delta = 30;   //delta参数决定增加红色和绿色通道的值

    for (int x = 0; x < newImage->width(); x++) {
        for (int y = 0; y < newImage->height(); y++) {
            oldColor = QColor(img->pixel(x, y));

            r = oldColor.red() + delta;
            g = oldColor.green() + delta;
            b = oldColor.blue();

            //将值域限制到[0,255]
            r = qBound(0, r, 255);
            g = qBound(0, g, 255);

            newImage->setPixel(x, y, qRgb(r, g, b));
        }
    }
    //存本地
    newImage->save("warm.bmp");
    p->load("warm.bmp");
    ui.label_2->setPixmap(QPixmap::fromImage(*p));
    ui.label_2->show();
}
void QtWidgetsApplication1::on_pushButton_3_clicked()
{
    img = new QImage;
    //读入失败，退出
    if (!(img->load("end.bmp"))) {
        QMessageBox::information(this, tr("System message"), tr("Operation failed"));
        delete img;
        return;
    }

    QImage* newImage = new QImage(*img);

    //滤波器
    int kernel[3][3] = { {0,-1,0},{-1,5,-1},{0,-1,0} };

    int kernelSize = 3;
    int sumKernel = 1;    //(-1)+(-1)+5+(-1)+(-1)
    int r, g, b;
    QColor color;

    for (int x = kernelSize / 2;x < newImage->width() - (kernelSize / 2);x++) {
        for (int y = kernelSize / 2;y < newImage->height() - (kernelSize / 2);y++) {
            r = 0;
            g = 0;
            b = 0;
            for (int i = -kernelSize / 2;i <= kernelSize / 2;i++) {
                for (int j = -kernelSize / 2;j <= kernelSize / 2;j++) {
                    color = QColor(img->pixel(x + i, y + j));
                    r += color.red() * kernel[kernelSize / 2 + i][kernelSize / 2 + j];
                    g += color.green() * kernel[kernelSize / 2 + i][kernelSize / 2 + j];
                    b += color.blue() * kernel[kernelSize / 2 + i][kernelSize / 2 + j];
                }
            }

            //将值域限制到[0,255]
            r = qBound(0, r / sumKernel, 255);
            g = qBound(0, g / sumKernel, 255);
            b = qBound(0, b / sumKernel, 255);

            newImage->setPixel(x, y, qRgb(r, g, b));
        }
    }
    //存本地
    newImage->save("sharpen.bmp");
    p->load("sharpen.bmp");
    ui.label_2->setPixmap(QPixmap::fromImage(*p));
    ui.label_2->show();
}
